/**
 * GminiRun.js - 文本处理和Gemini API调用主程序
 * 此模块负责读取TXT文件，调用Gemini API进行分析，并将结果保存到Excel文件中
 * by jeking
 * 主要功能：
 * 1. 读取指定目录下的TXT文件
 * 2. 调用Gemini API进行文本分析
 * 3. 将分析结果分类存储
 * 4. 生成Excel报告
 * 5. 自动备份和日志记录
 */

// 导入必要的依赖模块
const fileProcessor=require('./plugins/readyNtxt.js');  // 文件读取和预处理模块
const directoryPath='./dataIn/待处理TXT';              // TXT文件输入目录路径

const moveFile=require('./plugins/removeFile.js');      // 文件移动处理模块
const fs=require('fs');                                // Node.js文件系统模块
const path=require('path');                            // 路径处理模块

const { qusetionRes }=require('./plugins/qusetionTxt.js');     // 问题生成和处理模块
const moment=require('moment');                         // 日期时间处理模块

// 导入字符串过滤模块
const filterString=require('./plugins/filterString.js');// 字符串过滤和处理模块

// 日志模块初始化配置
const generateLog=require('./plugins/logger.js');       // 日志记录模块
const logFilePath=path.join(__dirname,'./log/appRun.log'); // 日志文件存储路径
const message='This is system log,下面是本次系统运行日志：';  // 初始日志消息
generateLog(logFilePath,message);                       // 写入系统启动日志

// 导入Gemini API调用模块
// const generateContent=require('./api/Gmini.js');           // Gemini API交互模块
// const generateContent=require('./api/Gmini2.0.js');           // Gemini API交互模块
const { generateContent }=require('./api/OpenAIWhisper.js');
const modelName="Gemini 2.0 Flash";
// 导入文件移动模块（用于数据备份）
const moveFiles=require('./plugins/fileMover.js');     // 文件移动工具
const sourceDir='./outExe/GminiResData';               // 结果数据源目录
const targetDir='./outExe/lastRunDataBackup';          // 数据备份目录

// 执行数据备份
moveFiles(sourceDir,targetDir)
  .then(() => {
    console.log('数据备份完成');
  })
  .catch(err => {
    console.error('数据备份失败:',err);
  });

// 导入Excel相关功能
const {
  createExcelFile,
  appendToExcel,
}=require('./plugins/outFile.js');                     // Excel文件处理模块

// 初始化结果数据数组
var resData=[];    // 存储分析成功的数据（标记为Y111）
var resError=[];   // 存储分析失败的数据（标记为N000）
var resOther=[];   // 存储其他异常情况的数据（不符合Y111或N000的情况）

/**
 * 延时函数 - 用于控制API调用频率，避免请求过于频繁
 * @param {number} ms - 延时时间（毫秒）
 * @returns {Promise} - 返回Promise以支持异步等待
 */
function delay(ms) {
  console.log('延时',ms,'毫秒');
  return new Promise(resolve => setTimeout(resolve,ms));
}

// 初始化文件处理相关变量
var readyTxtName='';                                   // 当前处理的文件名
const destDir='outExe/GminiResData/';                  // 结果输出目录
let currentDateTime=moment().format('MM-DD HH-mm-ss'); // 当前时间戳（用于文件命名）
const errTxtPath=path.join(destDir,'移出的TXT-'+currentDateTime);



// 初始化结果缓存数组
var arrryStr=[],   // 存储成功结果（Y111）的临时数组
  arrryStr2=[],  // 存储失败结果（N000）的临时数组
  arrryStr3=[];  // 存储其他结果的临时数组

/**
 * 处理TXT文件的主要函数
 * 负责读取、处理和分析TXT文件内容，并调用Gemini API进行分析
 * 
 * 工作流程：
 * 1. 读取指定目录下的所有TXT文件
 * 2. 对每个文件内容进行预处理
 * 3. 调用Gemini API进行分析
 * 4. 根据分析结果进行分类存储
 * 5. 生成Excel报告
 * 
 * @param {number} counts - 处理文件计数器，用于追踪处理进度
 * @returns {Promise<void>}
 */
async function processTxtFiles(counts = 0) {
  // 异步读取txt文件
  var counts = 1;
  // 初始化文件处理计数器

  try {
    let filePaths,filePath;
    do {
      // 获取一个新的、未读取的txt文件路径
      // 获取新的未处理TXT文件路径
      filePath = await fileProcessor.getNewTxtFilePath(directoryPath);

      if (filePath !== '' && filePath !== null) {
        // 打印当前处理的文件路径
        console.log('filePath:', filePath);

        // 排除文件是否不存在或为空
        // 读取文件内容
        // 读取文件内容并生成API请求文本
        const qusetion = await qusetionRes();
        const content = await fileProcessor.readFileContent(filePath, counts);
        var chatApiInputText = '"' + content.data + '"' + qusetion;
        // var sss=await qusetion
        var resultStr='';
        // console.log("chatApiInputText", chatApiInputText)
        try {
          // 调用Gemini API进行文本分析
          // 调用Gemini API进行文本分析
          const result = await generateContent(chatApiInputText); // 调用Gemini API分析并等待结果返回
          // 处理API返回结果
          // 根据API响应进行分类处理
          // // 将API响应转换为JSON字符串
          console.log('API返回:',result.parts[0].message.content);
          // console.log('API返回:',result);
          resultStr=JSON.stringify(result);
          
          // 打印API返回的JSON结果
          // console.log('API返回转Json:',resultStr.parts[0].message.content);
          // console.log('Generated Content:', result)
          if(
            result!==''&&
            result!==null&&
            result.reqStatus!=='error'&&
            result.reqStatus!=='ErrorResponse'&&
            result.reqStatus!=='ErrorRequest'&&
            result.reqStatus!=='ErrorMessage'&&
            result.apiError!=='接口请求未成功！请检查地址或网络!'&&
            result.parts.length>0
          ) {
            var JsonStr=JSON.stringify(result.parts[0].text);
              //  console.log('分析结果:', STR, ',返回TXT:', JsonStr);
            // var texTStr=result.parts[0].text;  
            var texTStr=result.parts[0].message.content;  
            console.log('分析结果texTStr:',texTStr);
            var STR=filterString.filter(texTStr);
         
            // console.log('API返回:',resultStr);  parts: [ { text: 'N000contact@sgitelecom.ma\n' } ],
            // console.log('API返回原始:',result);
            // console.log('API返回原始:',result.parts[0].text);
            const getEmail=result.parts[0].text.substring(5);; // 获取第邮箱
            // const result= // 从索引4开始截取字符串（去掉前4个字符）
            // console.log(result); // 输出 "info-maren.roselius@excellence.ag"
            console.log('getEmail:',getEmail); // 输出 "Y111"
            
            if(result.parts.length>0) {
              if(
                result.parts[0].text!==''&&
                result.parts[0].text!==null&&
                result.parts[0].text!==undefined
              ) {
                if(STR=='Y111') {
                  // console.log('STR结果:',STR);
                  arrryStr.push(content.email); // txt文件名，也就是邮箱名
                  arrryStr.push(modelName); // 记录使用的模型
                  arrryStr.push(STR); // 追加分析结果1或0  只保存前Y111
                  arrryStr.push(getEmail); // 追加分析结果1或0  保存全部字符数据
                  let currentDateTime=moment().format('MM-DD HH:mm:ss'); // 你可以根据需要自定义日期和时间的格式
                  arrryStr.push(currentDateTime); // 追加实时时间
                  // console.log("完成第", counts, "个文本数据处理,模型是:", "GminiChatV1.5");
                  // 正常处理后打印列表
                  resData.push(arrryStr);

                  // console.log('arrryStr:',arrryStr);
                  arrryStr=[];
                } else if(STR=='N000') {
                  arrryStr2.push(content.email); // txt文件名，也就是邮箱名
                  arrryStr2.push(modelName); // 记录使用的模型
                  arrryStr2.push(STR); // 追加分析结果1或0
                  arrryStr2.push(getEmail); // 追加分析结果1或0  保存全部字符数据
                  let currentDateTime=moment().format('MM-DD HH:mm:ss'); // 你可以根据需要自定义日期和时间的格式
                  arrryStr2.push(currentDateTime); // 追加实时时间
                  resError.push(arrryStr2);
                  // 正常处理后打印列表

                  // console.log('arrryStr2:',arrryStr2);
                  arrryStr2=[];
                } else {
                  // readyTxtName = filePath;
                  arrryStr3.push(content.email); // txt文件名，也就是邮箱名
                  arrryStr3.push(modelName); // 记录使用的模型
                  arrryStr3.push('NOT! 0 OR 1 ,'); // 返回了非1或0 的结果
                  arrryStr3.push(resultStr);
                  let currentDateTime=moment().format('MM-DD HH:mm:ss'); // 你可以根据需要自定义日期和时间的格式
                  arrryStr3.push(currentDateTime); // 追加实时时间
                  moveFile(filePath,errTxtPath,(err,message) => {
                    if(err) {
                      console.error('Error moving file:',err);
                    } else {
                      console.log('失败的txt挪出完成!',message);
                    }
                  });
                  resOther.push(arrryStr3);

                  // 正常处理后打印列表
                  // console.log('arrryStr3-1:',arrryStr3);
                  arrryStr3=[];
                }
              } else {
                console.log(  "result.parts[0]:",  result.parts[0])
                // readyTxtName = filePath;
                console.log('第',counts,'个,',result.parts.length);
                // arrryStr.push("返回数据异常"+JSON.stringify(result.reqStatus))
                arrryStr3.push(content.email); // txt文件名，也就是邮箱名
                arrryStr3.push(modelName); // 记录使用的模型
                arrryStr3.push('返回数据异常,'+resultStr); // API返回异常
                generateLog(logFilePath,'API返回数据异常:'+content.email); // + `${error}` + `--${nowTime}`);\
                arrryStr3.push(currentDateTime); // 追加实时时间let currentDateTime = moment().format('MM-DD HH:mm:ss'); // 你可以根据需要自定义日期和时间的格式
                arrryStr3.push(result); // 记录异常返回的全部数据
                moveFile(filePath,errTxtPath,(err,message) => {
                  if(err) {
                    console.error('Error moving file:',err);
                  } else {
                    console.log('失败的txt挪出完成！',message);
                  }
                });
                resOther.push(arrryStr3);
                // 正常处理后打印列表

                // console.log('arrryStr3-2:',arrryStr3);
                arrryStr3=[];
              }
            } else {
              // readyTxtName = filePath;
              // arrryStr.push("返回数据为空，" + JSON.stringify(result.reqStatus))
              arrryStr3.push(content.email); // txt文件名，也就是邮箱名
              arrryStr3.push(modelName); // 记录使用的模型
              arrryStr3.push('返回数据格式不匹配,'); // API返回异常
              console.log('第',counts,'个文本数据chatAPI返回异常:',arrryStr);
              generateLog(logFilePath,'第'+counts+'个文件分析'); // + `${error}` + `--${nowTime}`);
              let currentDateTime=moment().format('MM-DD HH:mm:ss'); // 你可以根据需要自定义日期和时间的格式
              arrryStr3.push(JSON.stringify(result)); // 记录异常返回的全部数据
              arrryStr3.push(currentDateTime); // 追加实时时间
              moveFile(filePath,errTxtPath,(err,message) => {
                if(err) {
                  console.error('Error moving file:',err);
                } else {
                  console.log('失败的txt挪出完成！',message);
                }
              });
              resOther.push(arrryStr3);
              // 正常处理后打印列表

              console.log('arrryStr3-3:',arrryStr3);
              arrryStr3=[];
            }
          } else {
            // readyTxtName = filePath;
            // arrryStr.push("返回为空！" + (result.reqStatus))
            arrryStr3.push(content.email); // txt文件名，也就是邮箱名
            arrryStr3.push(modelName); // 记录使用的模型
            if(result.error.error.code=400) {
              arrryStr3.push(result.error.error.message); // API返回异常
            } else {
              arrryStr3.push('返回数据为空！,'); // API返回异常
            }
            arrryStr3.push(JSON.stringify(result)); // 记录异常返回的全部数据
            let currentDateTime=moment().format('MM-DD HH:mm:ss'); // 你可以根据需要自定义日期和时间的格式
            arrryStr3.push(currentDateTime); // 追加实时时间
            console.log(
              '第',
              counts,
              '个文本分析异常,chatAPI返回无效格式或接口不存在!',
              JSON.stringify(result)
            );
            // console.log("apiResult:", JSON.stringify(result), arrryStr)
            generateLog(logFilePath,'result为空:'+JSON.stringify(result)); // + `${error}` + `--${nowTime}`);
            moveFile(filePath,errTxtPath,(err,message) => {
              if(err) {
                console.error('Error moving file:',err);
              } else {
                console.log('失败的txt挪出完成！',message);
              }
            });
            resOther.push(arrryStr3);

            // 正常处理后打印列表
            // console.log('arrryStr3-4:',arrryStr3);
            arrryStr3=[];
          }

          // console.log("arrryStr2:", arrryStr2)
          // console.log("arrryStr3:", arrryStr3)
        } catch(error) {
          // readyTxtName = filePath;
          // console.error('ApiError:', error);
          // arrryStr.push("接口异常！" + JSON.stringify(error))
          // 根据错误类型进行分类处理
          let errorType = '未知错误';
          if (error instanceof TypeError) {
            errorType = '类型错误';
          } else if (error instanceof SyntaxError) {
            errorType = '语法错误';
          } else if (error instanceof Error) {
            errorType = 'API错误';
          }
          
          // 格式化错误信息
          const errorMessage = `第${counts}个文件处理失败 - 错误类型: ${errorType} - 错误信息: ${error.message || '未知错误'}`;
          console.log(errorMessage);
          generateLog(logFilePath, errorMessage);
          // arrryStr3.push(content.email); // txt文件名，也就是邮箱名-1   前面会环节自动添加了

          // arrryStr3.push(modelName); // 记录使用的模型-2
          arrryStr3.push('异常错误导致循环中断！'); // API返回异常-3
          arrryStr3.push(error.stack||error.message); // 记录错误堆栈信息或消息
          // arrryStr3.push((error)); //记录错误-4
          let currentDateTime=moment().format('MM-DD HH:mm:ss'); // 你可以根据需要自定义日期和时间的格式
          arrryStr3.push(currentDateTime); // 追加实时时间-5
          generateLog(logFilePath,error); // + `${error}` + `--${nowTime}`);
          moveFile(filePath,errTxtPath,(err,message) => {
            if(err) {
              console.error('Error moving file:',err);
            } else {
              console.log('失败的txt挪出完成！',message);
            }
          });
          const formattedArray=arrryStr3.map(item => (typeof item==='string'? item:JSON.stringify(item)));
          resOther.push(formattedArray);
          // console.log('arrryStr3-5:',formattedArray);
          // arrryStr3 = [];
        } finally {
          console.log(
            '完成第',
            counts,
            '个TXT文件处理,模型是:',
            modelName
          );
          // 三张缓存表数据追加到主表
          arrryStr=[];
          arrryStr2=[];
          arrryStr3=[];
          counts++;
        }
      } else {
        //   arrryStr.push(error)
        // readyTxtName = filePath;
        console.log('TXT文件内容为空或已处理完！');
        generateLog(logFilePath,'文件处理完！共计:'+(counts-1)+'个。'); // + `${error}` + `--${nowTime}`);
      }
      await delay(3000); // 延迟5秒，避免API封杀！

    } while(filePath); // 当没有新的未读取文件时，filePath将为null/undefined，退出循环

    let currentDateTime=moment().format('MM-DD HH-mm-ss'); // 你可以根据需要自定义日期和时间的格式

    console.log('Y111:',resData.length);
    console.log('N000:',resError.length);
    console.log('Not1/0:',resOther.length);
    // appendToExcel('./outExe/纯文本数据分析结果-GminiV1.5.xlsx', currentDateTime, resData); // 写出失败记录 // 追加写出表格文件
    if(resData.length>0) {
      createExcelFile(
        resData,
        './outExe/GminiResData/为1的-'+currentDateTime+'.xlsx',
        'sheet1'
      );
    }
    if(resError.length>0) {
      createExcelFile(
        resError,
        './outExe/GminiResData/为0的-'+currentDateTime+'.xlsx',
        'sheet1'
      );
    }
    if(resOther.length>0) {
      createExcelFile(
        resOther,
        './outExe/GminiResData/非1或0&Error-'+currentDateTime+'.xlsx',
        'sheet1'
      );
    }
    generateLog(
      logFilePath,
      '完成全部'+(counts-1)+'个文本数据处理！并保存了全部数据！'
    ); // + `${error}` + `--${nowTime}`);
  } catch(error) {
    // 处理错误
    console.error('An error occurred:',error);
    generateLog(logFilePath,error); // + `${error}` + `--${nowTime}`);
  }
}

/**
 * 处理API返回结果的函数
 * 根据API返回的结果进行分类存储和Excel报告生成
 * 
 * 分类规则：
 * - Y111: 分析成功的数据，存储到resData数组
 * - N000: 分析失败的数据，存储到resError数组
 * - 其他: 异常情况数据，存储到resOther数组
 * 
 * @param {object} content - 原始文件内容
 * @param {object} result - API返回的分析结果
 * @param {string} resultStr - API返回结果的字符串形式
 * @param {number} counts - 处理文件计数
 */
async function handleResult(content,result,resultStr,counts) {
  const currentDateTime=moment().format('MM-DD HH:mm:ss');
  let resultArray=[];

  if(result.parts[0].text!==''&&result.parts[0].text!==null) {
    const STR=filterString.filter(result.parts[0].text);
    resultArray.push(content.email,modelName,STR,currentDateTime);

    if(STR==='Y111') {
      resData.push(resultArray);
    } else if(STR==='N000') {
      resError.push(resultArray);
    } else {
      resultArray[2]='NOT! 0 OR 1 ,'+resultStr;
      moveFile(filePath,errTxtPath,(err,message) => {
        if(err) {
          console.error('Error moving file:',err);
        } else {
          console.log('失败的txt挪出完成!',message);
        }
      });
      resOther.push(resultArray);
    }
  } else {
    // Handle empty or null text
  }
}

// 开始处理txt文件
processTxtFiles();